table of contents
SHMGET(2) | Руководство программиста Linux | SHMGET(2) |
ИМЯ¶
shmget - выделяет общий сегмент памяти
ОБЗОР¶
#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t key, size_t size, int shmflg);
ОПИСАНИЕ¶
Вызов shmget() возвращает идентификатор общего сегмента памяти, соответствующего значению аргумента key. Если значение key равно IPC_PRIVATE или если key не равно IPC_PRIVATE, но не существует общего сегмента памяти, который бы соответствовал значению key и в shmflg есть флаг IPC_CREAT, то создаётся новый общий сегмент памяти размером size, округлённым до значения, кратного PAGE_SIZE.
Если в shmflg одновременно указаны IPC_CREAT и IPC_EXCL и для значения key уже существует общий сегмент памяти, то вызов shmget() завершается с ошибкой и errno присваивается EEXIST (такой же результат как с O_CREAT | O_EXCL у open(2)).
Значение shmflg составляется из следующих флагов:
- IPC_CREAT
- Служит для создания нового сегмента. Если этого флага нет, то вызов shmget() будет искать сегмент, соответствующий key, и затем проверит, имеет ли пользователь права на доступ к сегменту.
- IPC_EXCL
- Используется совместно с IPC_CREAT для того, чтобы отказаться от создания при наличии сегмента.
- mode_flags
- В младших 9 битах задаются права для владельца, группы и всех остальных. Формат значения совпадает с аргументом mode вызова open(2). В данный момент бит выполнения системой не используются.
- SHM_HUGETLB (начиная с Linux 2.6)
- Выделять сегмент используя «огромные страницы». Дополнительную информацию смотрите в файле исходного кода ядра Documentation/vm/hugetlbpage.txt.
- SHM_NORESERVE (начиная с Linux 2.6.15)
- Этот флаг нужен для того же, что и флаг MAP_NORESERVE у mmap(2). Он указывает не резервировать место в пространстве подкачки для этого сегмента. Операцией резервирования места в пространстве подкачки гарантируется, что сегмент можно изменить. Если место не резервировать, то при записи можно получить сигнал SIGSEGV, если кончится физическая память. Смотрите также обсуждение файла /proc/sys/vm/overcommit_memory в proc(5).
Если создаётся новый общий сегмент памяти, то его содержимое инициализируется нулями, а соответствующая ему структура данных shmid_ds (см. shmctl(2)) следующим образом:
- Полям shm_perm.cuid и shm_perm.uid присваиваются значения эффективного идентификатора пользователя вызывающего процесса.
- Полям shm_perm.cgid и shm_perm.gid присваиваются значения эффективного идентификатора группы вызывающего процесса.
- Младшим 9 битам shm_perm.mode присваивается значение младших 9 бит shmflg.
- Полю shm_segsz присваивается значение size.
- Полям shm_lpid, shm_nattch, shm_atime и shm_dtime присваивается 0.
- Полю shm_ctime присваивается значение текущего времени.
Если общий сегмент памяти уже существует, то проверяются права доступа к нему и не помечен ли он для удаления.
ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ¶
При успешном выполнении возвращается корректный идентификатор сегмента shmid и -1 в случае ошибки.
ОШИБКИ¶
В случае возникновения ошибки errno может принимать следующие значения:
- EACCES
- Пользователь не имеет прав доступа к общему сегменту памяти и не имеет мандата CAP_IPC_OWNER.
- EEXIST
- Указан флаг IPC_CREAT | IPC_EXCL и сегмент существует.
- EINVAL
- Был создан новый сегмент и size < SHMMIN или size > SHMMAX, или новый сегмент не создан, т.к. существует сегмент с указанным ключом, но size больше размера этого сегмента.
- ENFILE
- Достигнуто максимальное количество открытых файлов в системе.
- ENOENT
- Не существует сегмента для ключа key и флаг IPC_CREAT не указан.
- ENOMEM
- Не хватает памяти для выделения под перерасход сегмента.
- ENOSPC
- Все возможные идентификаторы сегментов уже распределены (SHMMNI) или размер выделяемого сегмента превысит системные лимиты по общей памяти (SHMALL).
- EPERM
- Указан флаг SHM_HUGETLB, но у вызывающего нет прав (нет мандата CAP_IPC_LOCK).
СООТВЕТСТВИЕ СТАНДАРТАМ¶
SVr4, POSIX.1-2001.
Флаг SHM_HUGETLB является непереносимым расширением Linux.
ЗАМЕЧАНИЯ¶
Включение файлов <sys/types.h> и <sys/ipc.h> не требуется в Linux или любых версий POSIX. Однако, некоторые старые реализации требуют включения данных заголовочных файлов, и это также требуется по SVID. В приложениях, которые нужно перенести на такие старые системы, может потребоваться включить данных заголовочные файлы.
IPC_PRIVATE не поле флага, а тип key_t. Если key равно этому значению, то системный вызов игнорирует всё кроме 9-ти младших битов shmflg и создаёт новый общий сегмента памяти (при успешном выполнении).
Ниже приведены лимиты ресурсов на общий сегмент памяти, влияющие на вызов shmget():
- SHMALL
- Максимальное количество страниц общей памяти в системе (в Linux это ограничение можно получить и изменить через /proc/sys/kernel/shmall).
- SHMMAX
- Максимальный размер общего сегмента памяти в байтах в системе: зависит от политики (в Linux это ограничение можно получить и изменить через /proc/sys/kernel/shmmax).
- SHMMIN
- Минимальный размер общего сегмента памяти в байтах в системе: зависит от реализации (в настоящий момент равно 1 байту, хотя на самом деле минимальный выделяемый размер равен PAGE_SIZE).
- SHMMNI
- Максимальное количество сегментов общей памяти в системе: зависит от реализации (в настоящий момент — 4096, до Linux 2.3.99 было равно 128; в Linux это ограничение можно получить и изменить через /proc/sys/kernel/shmmni).
Реализацией не ограничивается максимальное количество общих сегментов памяти на процесс (SHMSEG).
Замечания, касающиеся Linux¶
В Linux до версии 2.3.30 вызов shmget() возвращал значение EIDRM, если общий сегмент памяти был запланирован к удалению.
ДЕФЕКТЫ¶
Имя IPC_PRIVATE, возможно, было выбрано неудачно, IPC_NEW отражает смысл действия более ясно.
СМОТРИТЕ ТАКЖЕ¶
shmat(2), shmctl(2), shmdt(2), ftok(3), capabilities(7), shm_overview(7), svipc(7)
2012-05-31 | Linux |